<?php

declare (strict_types=1);
namespace App\Model;

use Hyperf\DbConnection\Db;

/**
 * @property int $id 
 * @property int $appid 
 * @property int $type 
 * @property string $content 
 * @property string $account 
 * @property string $to_account 
 * @property int $time 
 */
class Msg extends BaseModel
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'msg';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [];
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'appid' => 'integer', 'type' => 'integer', 'time' => 'integer'];

    private static $_pagesize = 20;

    /**
     * 获取聊天记录
     * @param $appid
     * @param $array
     * @return array|string
     */
    public static function getList($appid, $array)
    {
        $account    = $array['account'] ?? '';
        $to_account = $array['to_account'] ?? '';
        $page       = isset($array['page']) ? intval($array['page']) : 1;
        $size       = isset($array['size']) ? intval($array['size']) : self::$_pagesize;

        if (empty($account))
            return 'account is null';
        if (empty($to_account))
            return 'to_account is null';

        $offect   = self::p_offset($page,$size);
        $pagesize = self::p_size($size);

        $sql = "
select a.id,a.account,a.content,a.status,a.time,a.to_account,b.username,b.avatar from hyy_msg a left join hyy_user_bind b on b.appid=? and b.account=a.account 
where a.appid=? and a.account=? and a.to_account=? 
union 
select a.id,a.account,a.content,a.status,a.time,a.to_account,b.username,b.avatar from hyy_msg a left join hyy_user_bind b on b.appid=? and b.account=a.account 
where a.appid=? and a.account=? and a.to_account=? 
order by time desc limit $offect,$pagesize;";

        $bindings = [$appid,$appid,$account,$to_account,$appid,$appid,$to_account,$account];
        $list     = Db::select($sql, $bindings);

        if ($list)
        {
            foreach ($list as &$val)
            {
                $val->content = unserialize($val->content);
            }
        }

        return [
            'list' => $list
        ];
    }

    public static function getAfterMsg($appid, $account, $page)
    {
        $offect = ($page-1) * self::$_pagesize;
        $pagesize = self::$_pagesize;


        $sql = "select account from `hyy_msg` where `appid` = ? and `account` = ? group by to_account limit 8 offset 0";
        $bindings =  [$appid,$account];
        $list = Db::select($sql,$bindings);


        /*
        $list = self::where('appid','=',$appid)
            ->where('account','=',$account)
            ->groupBy(['to_account'])
            ->orderBy('time', 'desc')
            ->offset($offect)
            ->limit(self::$_pagesize)
            ->toSql();
//            ->select();
        */


        return $list;
    }

    /**
     * 获取有聊天记录的好友列表
     * @param $appid
     * @param array $array
     * @return array
     */
    public static function getFriedMsg($appid, array $array)
    {
        $account = $array['account'] ?? '';
        $page    = isset($array['page']) ? intval($array['page']) : 1;
        $size    = isset($array['size']) ? intval($array['size']) : self::$_pagesize;

        if (empty($account))
            return 'account is null - model';

        $offect   = self::p_offset($page,$size);
        $pagesize = self::p_size($size);

        $sql = "
SELECT
	id,0 as g_id,content,account,to_account,time,'' as username,'' as avatar,'private' as is_from 
FROM
	(
	SELECT
		id,content,account,to_account,status,time  
	FROM
		 hyy_msg
	WHERE
		time IN (
		SELECT
			MAX( time ) 
		FROM
			hyy_msg 
		WHERE
			appid = ? AND
			(account = ? 
			OR to_account = ?) 
		
		GROUP BY
			CONCAT(
			IF
				( account > to_account, account, to_account),
			IF
			( account < to_account, account, to_account))) 
		AND (appid = ? AND (to_account = ? OR account = ?) ) 
	  ORDER BY id DESC
	) c 
UNION 
SELECT  
    a.id,a.g_id,a.content,a.account,0 as to_account,a.created_at as time,b.title as username,b.avatar,'group' as is_from 
FROM 
  (SELECT id,g_id,content,account,created_at FROM hyy_group_msg WHERE g_id IN(SELECT g_id FROM hyy_group_user WHERE account=?) ORDER BY id DESC LIMIT 9999999) a
LEFT JOIN hyy_group b ON b.id = a.g_id 
GROUP BY a.g_id 

ORDER BY time DESC
";

        $bindings =  [$appid,$account,$account,$appid,$account,$account,$account];
        $list     = Db::select($sql . " LIMIT $offect,$pagesize", $bindings);

        if ($list)
        {
            foreach ($list as &$val)
            {
                $val->content = unserialize($val->content);

                // 私聊的
                if ($val->is_from == 'private')
                {
                    // 转换account 保证都是对方的account
                    $to_account = $val->account;
                    if ($account == $val->account)
                    {
                        $to_account = $val->to_account;
                    }

                    $user = UserBind::where(['account'=>$to_account,'appid'=>$appid])->first(['username','avatar']);

                    $val->account  = $to_account;
                    $val->username = $user->username ?? '';
                    $val->avatar   = $user->avatar ?? '';

                    // 未读消息数
                    $val->no_read = self::getNoread($appid,$account,$to_account);

                    unset($val->to_account);
                }else if ($val->is_from == 'group')
                {
                    // 未读消息数
                    $val->no_read = self::getNoreadGroup($account,$val->g_id);
                }

            }
        }

        return [
            'list'  => $list
        ];

    }

    /**
     * 更新消息状态
     * @param $appid
     * @param $data
     * @param int $status
     * @return bool
     */
    public static function updateStatus($appid,$data,$status = 1)
    {
        $msg_id     = isset($data['msg_id']) ? intval($data['msg_id']) : 0;
        $account    = $data['account'] ?? '';
        $to_account = $data['to_account'] ?? '';

        if (empty($account))
            return 'account is null';

        if (empty($to_account))
            return 'to_account is null';

        $row = 0;
        if (intval($msg_id) > 0)
        {
            $row = self::where(['id'=>$msg_id])->update(['status'=>intval($status)]);
            if ($row > 0)
                return true;
        }else{
            $count = self::where(['appid'=>$appid,'account'=>$to_account,'to_account'=>$account,'status'=>2])->count();
            if ($count > 0)
            {
                $row = self::query()->where([
                        'appid'=>$appid,
                        'account'=>$to_account,
                        'to_account'=>$account,
                        'status' => 2
                    ])->update(['status'=>intval($status)]);
            }

        }

        return ['update_num' => $row];
    }

    /**
     * @param $appid
     * @param $account
     * @param $to_account
     * @return int
     */
    public static function getNoread($appid, $account, $to_account)
    {
        $where = [
            'appid'      => $appid,
            'account'    => $to_account,
            'to_account' => $account,
            'status'     => 2,
        ];
        $count = self::where($where)->count();

        return (int)$count;
    }

    /**
     * @param $account
     * @param $g_id
     * @return int
     */
    private static function getNoreadGroup($account, $g_id)
    {
        $sql = "select count(*) total from hyy_group_msg where g_id=? and id>?";

        $last_ack_msgid = GroupUser::where(['g_id'=>$g_id,'account'=>$account])->value('last_ack_msgid');

        $data = Db::select($sql,[$g_id,$last_ack_msgid]);

        return (int)$data[0]->total;
    }
}